package com.ktjy.service.impl;

import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.ktjy.dto.LoginUser;
import com.ktjy.dto.WorkFlowDTO;
import com.ktjy.mapper.TbActivityMapper;
import com.ktjy.pojo.TbActivity;
import com.ktjy.service.IWorkFlowService;
import com.ktjy.utils.Constants;
import com.ktjy.utils.PageUtil;
import com.ktjy.vo.ActCommentEntity;
import com.ktjy.vo.ActTaskEntity;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.impl.identity.Authentication;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Comment;
import org.activiti.engine.task.Task;
import org.activiti.engine.task.TaskQuery;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class WorkFlowServiceImpl implements IWorkFlowService {
    @Autowired
    RuntimeService runtimeService;
    @Autowired
    TaskService taskService;
    @Autowired
    RepositoryService repositoryService;
    @Autowired
    TbActivityMapper activityMapper;

    @Override
    public void startProcess(String processDefinitionKey,Integer id) {
        //1.启动
        // 业务Key，它对应act_ru_execution流程执行实例表中的BUSINESS_KEY列(这个值可以自定义)默认格式：
        String businessKey = processDefinitionKey + ":" + id;
        // 流程变量, 用于指定下一个任务的任务处理人
        Map<String, Object> variables = new HashMap<String,Object>();
        LoginUser loginUser=(LoginUser) SecurityContextHolder.getContext()
                .getAuthentication().getPrincipal();
        variables.put("username", loginUser.getRealName()); //任务处理人为当前登录用户
        ProcessInstance processInstance = runtimeService
                .startProcessInstanceByKey(processDefinitionKey, businessKey, variables);

        //2.完成提交任务
        Task task = taskService.createTaskQuery()
                .processInstanceId(processInstance.getId())
                .singleResult();
        taskService.complete(task.getId());

        //3. 流程启动成功后，还需要更新下当前活动的状态
        UpdateWrapper uw=new UpdateWrapper();
        uw.eq("id",id);
        uw.set("status", Constants.STATE_TWO);//审核中
        activityMapper.update(uw);
    }

    // 查询当前登录用户的待办任务
    @Override
    public PageUtil findTask(WorkFlowDTO workFlowDTO,
                             Integer pageNo, Integer pageSize) {
        PageUtil pageUtil=new PageUtil();
        pageUtil.setPageNo(pageNo);
        pageUtil.setPageSize(pageSize);
        //1、得到任务办理人信息
        LoginUser loginUser=(LoginUser) SecurityContextHolder.getContext()
                .getAuthentication().getPrincipal();
        //2、查询当前登录用户的所有待办理任务的总数
        TaskQuery taskQuery = taskService.createTaskQuery()
                .taskAssignee(loginUser.getRealName());
        long count = taskQuery.count();
        pageUtil.setTotalCount(count);
        if(count%pageSize==0){
            pageUtil.setTotalPageCount(count/pageSize);
        }else{
            pageUtil.setTotalPageCount(count/pageSize+1);
        }
        //3、查询当前登录用户的所有待办理任务列表
        List<Task> tasks = taskQuery.listPage((pageNo - 1) * pageSize, pageSize);
        List<ActTaskEntity> list=new ArrayList<>();
        if (!ObjectUtils.isEmpty(tasks)) {
            for (Task task : tasks) {
                ActTaskEntity actTaskEntity=new ActTaskEntity();
                //对象属性复制
                BeanUtils.copyProperties(task,actTaskEntity);
                list.add(actTaskEntity);
            }
            pageUtil.setData(list);
        }
        return pageUtil;
    }

    // 根据任务ID查询请假单的信息
    @Override
    public TbActivity findActivityByTaskId(String taskId) {
        //1、根据任务ID查询任务实例
        Task task = taskService.createTaskQuery()
                .taskId(taskId).singleResult();
        //2、从任务实例对象中取出流程实例ID
        String processInstanceId = task.getProcessInstanceId();
        //3、根据流程实例ID查询流程实例
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
                .processInstanceId(processInstanceId).singleResult();
        //4、从流程实例对象中取出business_key，business_key数据格式为： LeaveBill:1 这个1为请假单ID
        String businessKey = processInstance.getBusinessKey();
        String businessId = businessKey.split(":")[1]; // 得到business_key中的请假单ID
        //5、最后根据业务ID查询业务对象信息
        return activityMapper.selectById(businessId);
    }

    // 根据任务ID查询批注信息
    @Override
    public List<ActCommentEntity> findCommentByTaskId(String taskId) {
        //1、根据任务ID查询任务实例
        Task task = taskService.createTaskQuery()
                .taskId(taskId).singleResult();
        //2、从任务里面取出流程实例ID
        String processInstanceId = task.getProcessInstanceId();
        //3、通过流程实例ID得到其所有的批注列表信息
        List<Comment> comments = taskService.getProcessInstanceComments(processInstanceId);
        //因为上述comments在转换成JSON格式时会出错，所以这里自定义一个名为ActCommentEntity实体类
        List<ActCommentEntity> list = new ArrayList<>();
        if (!ObjectUtils.isEmpty(comments)) {
            for (Comment comment : comments) {
                ActCommentEntity entity = new ActCommentEntity();
                BeanUtils.copyProperties(comment, entity);
                list.add(entity);
            }
        }
        return list;
    }

    @Override
    public void completeTask(WorkFlowDTO workFlowDTO) {
        //1、获取从前端传递过来的任务ID
        String taskId = workFlowDTO.getTaskId();
        //2、获取从前端传递过来的连接名称
        String outcome = workFlowDTO.getOutcome();
        // 因为任务处理完后还需要修改当前请假单的审批状态
        //3、获取从前端传递过来的请假单ID
        Integer businessId = workFlowDTO.getBusinessId();
        //4、获取从前端传递过来的批注信息
        String comment = workFlowDTO.getComment();

        //5、根据任务ID查询任务实例
        Task task = taskService.createTaskQuery()
                .taskId(taskId).singleResult();
        //6、从任务里面取出流程实例ID
        String processInstanceId = task.getProcessInstanceId();
        //7、设置批注人名
        LoginUser loginUser=(LoginUser) SecurityContextHolder.getContext()
                .getAuthentication().getPrincipal();
        //Authentication需导包： import org.activiti.engine.impl.identity.Authentication;
        Authentication.setAuthenticatedUserId(loginUser.getRealName());
        //8、添加批注信息 (act_hi_comment批注表)
        taskService.addComment(taskId, processInstanceId, "[" + outcome + "]" + comment);
        //9、完成任务
        Map<String, Object> variables = new HashMap<>();
        variables.put("outcome", outcome);
        // 在执行完下面taskService.complete()代码完成任务(提交而非放弃的情况下)，会第一时间触发TaskListenerImpl任务监听器类的notify()方法(可以在监听器类中打上断点进行调试)。
        taskService.complete(taskId, variables);
        //10、判断任务是否结束
        // 上面调用taskService.complete()执行完任务后，只要是任务完毕，这条任务数据在act_ru_execution表中会被删除，使用processInstanceId任务ID去查询，得到的processInstance结果会是null
        ProcessInstance processInstance = runtimeService
                .createProcessInstanceQuery()
                .processInstanceId(processInstanceId).singleResult();
        if(processInstance==null){// 等于null说明流程结束了
            // 通过请假ID查询该请假的详细信息
            UpdateWrapper uw=new UpdateWrapper();
            uw.eq("id",businessId);

            if (outcome.equals("驳回")) {
                uw.set("status", Constants.STATE_THREE);//3 表示已驳回
            } else {
                uw.set("status", Constants.STATE_FOUR);//4 表示已通过
            }
            activityMapper.update(uw);
        }
    }
}
